" >>>>>>>> 基本配置 >>>>>>>>
" 语法高亮
syntax on
" 设置<Leader>键，默认为\
let mapleader = "\\"
" 编码格式
set encoding=UTF-8
" 开启行号显示
set number
" 行号开关快捷键
map <C-n> :set number!<CR>
" 水平分割窗口快捷键
nnoremap <Leader>ws :sp<cr>
" 垂直分割窗口快捷键
nnoremap <Leader>wv :vsp<cr>
" 切换窗口快捷键
nnoremap <Leader>ww <C-w><C-w>
nnoremap <Leader>wh <C-w>h
nnoremap <Leader>wj <C-w>j
nnoremap <Leader>wk <C-w>k
nnoremap <Leader>wl <C-w>l
" 关闭当前窗口快捷键
nmap <Leader>wc :close<cr>
" 关闭其他当前窗口快捷键
nmap <Leader>wo :only<cr>
" 调整窗口大小
nmap <Leader>w> :10wincmd><cr>
nmap <Leader>w< :10wincmd<<cr>
nmap <Leader>w+ :10wincmd+<cr>
nmap <Leader>w- :10wincmd-<cr>
nnoremap <Leader>w= <C-w>=
" buffer快捷键
nmap <Leader>bn :bn<cr>
nmap <Leader>bp :bp<cr>
nmap <Leader>bf :bf<cr>
nmap <Leader>bl :bl<cr>
nmap <Leader>bd :bd<cr>
" 终端颜色
set t_Co=256
set background=dark
" 高亮显示当前行/列
set cursorline
highlight CursorLine cterm=NONE ctermbg=brown ctermfg=white guibg=brown guifg=white
" set cursorcolumn
" highlight CursorColumn cterm=NONE ctermbg=gray ctermfg=NONE guibg=darkred guifg=white
" 高亮显示第80列
set colorcolumn=80
highlight colorcolumn cterm=NONE ctermbg=brown ctermfg=white guibg=brown guifg=white

" tab和空格显示
" map <F7> :set list!<CR>
" set list
" set listchars=tab:┊-,space:`,trail:┊
" set listchars=tab:┊-,trail:┊
let g:list_toggle = 1
function! ListToggle()
	if g:list_toggle == 0
		set nolist
		let g:list_toggle = 1
	elseif g:list_toggle == 1
		set list
		set listchars=tab:┊-,trail:┊
		let g:list_toggle = 2
	elseif g:list_toggle == 2
		set list
		set listchars=tab:┊-,space:`,trail:┊
		let g:list_toggle = 0
	endif
endfunction
command! -nargs=0 ListToggle call ListToggle()
call ListToggle()
map <F7> :ListToggle<CR>

" 开启实时搜索功能
set incsearch
" 高亮显示搜索结果
set hlsearch
nmap <Leader>hs :set hlsearch!<cr>

" 不自动换行
" set nowrap
" 在特定字符换行
set linebreak
" 终端滚动时时刻保留n行在界面中
" set scrolloff=3

" 高亮显示匹配的括号
set showmatch

"""""""""""""""""""""""""""""""""""""""""
" 实时生效vim配置
"""""""""""""""""""""""""""""""""""""""""
" 让配置变更立即生效
autocmd! BufWritePost ~/.vimrc source %
" 在另外一个vim中加载被修改过的vimrc
cnoreabbrev vimreload so ~/.vimrc

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" cscope setting
" 先用cscope -Rbq命令生产索引文件cscope.in.out cscope.out cscope.po.out
" 查看帮助:cs help
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
if has("cscope")
	" set csprg=/usr/bin/cscope
	set csto=0
	set cst
	set nocsverb
	if filereadable("cscope.out")
		cs add cscope.out
	elseif $CSCOPE_DB != ""
		cs add $CSCOPE_DB
	endif
	set csverb
endif

" <<<<<<<< 基本配置 <<<<<<<<

" >>>>>>>> 插件管理 >>>>>>>>
" 使用vim-plug管理插件: https://github.com/junegunn/vim-plug
" vim-plug从github下载插件，可以从github.com获取插件的相关文档
call plug#begin('~/.vim/plugged')

" 窗口最大化/还原
" >>>>>> ZoomWin >>>>>>
Plug 'regedarek/ZoomWin'
" 窗口最大化/还原快捷键
map <F3> :ZoomWin<CR>
" <<<<<< ZoomWin <<<<<<

" ------ 目录树 ------
" >>>>>> NERDTree >>>>>>
" Fixed: E117: Unknown function: ALEGetStatusLine
function! ALEGetStatusLine()
	" ALEGetStatusLine函数已被删除，这里提供一个桩函数避免报错
endfunction
Plug 'preservim/nerdtree', { 'on':  'NERDTreeToggle' }
" NERDTree配套插件
Plug 'Xuyuanp/nerdtree-git-plugin'
Plug 'tiagofumo/vim-nerdtree-syntax-highlight'
Plug 'jistr/vim-nerdtree-tabs'
" 内置在NERDTree操作区的一些基本操作
" ?: 快速帮助文档
" o: 打开一个目录或者打开文件，创建的是buffer，也可以用来打开书签
" go: 打开一个文件，但是光标仍然留在NERDTree，创建的是buffer
" t: 打开一个文件，创建的是Tab，对书签同样生效
" T: 打开一个文件，但是光标仍然留在NERDTree，创建的是Tab，对书签同样生效
" i: 水平分割创建文件的窗口，创建的是buffer
" gi: 水平分割创建文件的窗口，但是光标仍然留在NERDTree
" s: 垂直分割创建文件的窗口，创建的是buffer
" gs: 和gi，go类似
" x: 收起当前打开的目录
" X: 收起所有打开的目录
" e: 以文件管理的方式打开选中的目录
" D: 删除书签
" P: 大写，跳转到当前根路径
" p: 小写，跳转到光标所在的上一级路径
" K: 跳转到第一个子路径
" J: 跳转到最后一个子路径
" <C-j>和<C-k>: 在同级目录和文件间移动，忽略子目录和子文件
" C: 将根路径设置为光标所在的目录
" u: 设置上级目录为根路径
" U: 设置上级目录为跟路径，但是维持原来目录打开的状态
" r: 刷新光标所在的目录
" R: 刷新当前根路径
" I: 显示或者不显示隐藏文件
" f: 打开和关闭文件过滤器
" q: 关闭NERDTree
" A: 全屏显示NERDTree，或者关闭全屏

" NERDTree开关快捷键
noremap <F2> :NERDTreeToggle<CR>

" 启动vim时自动启动NERDTree
" autocmd vimenter * NERDTree

" 不指定文件启动vim时自动启动NERDTree
autocmd StdinReadPre * let s:std_in=1
autocmd VimEnter * if argc() == 0 && !exists("s:std_in") | exe 'NERDTree' "." | endif

" 指定目录启动vim时自动启动NERDTree
autocmd StdinReadPre * let s:std_in=1
autocmd VimEnter * if argc() == 1 && isdirectory(argv()[0]) && !exists("s:std_in") |
			\ exe 'NERDTree' argv()[0] | wincmd p | ene | exe 'cd '.argv()[0] | endif

" 只剩NERDTree窗口时关闭vim
autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTree") &&
			\ b:NERDTree.isTabTree()) | q | endif

" 只剩NERDTree窗口时关闭vim或者tab
autocmd BufEnter * if tabpagenr('$') == 1 && winnr('$') == 1 &&
			\ exists('b:NERDTree') && b:NERDTree.isTabTree() | quit | endif

" 保持NERDTree buffer的内容
autocmd BufEnter * if bufname('#') =~ 'NERD_tree_\d\+' &&
			\ bufname('%') !~ 'NERD_tree_\d\+' && winnr('$') > 1 |
			\ let buf=bufnr() | buffer# | execute "normal! \<C-W>w" |
			\ execute 'buffer'.buf | endif

" 显示行号
let NERDTreeShowLineNumbers=1
let NERDTreeAutoCenter=1
" 显示隐藏文件
let NERDTreeShowHidden=1
" 设置宽度
let NERDTreeWinSize=32
" 忽略以下文件的显示
let NERDTreeIgnore=['\.pyc','\~$','\.swp']
" 显示书签列表
let NERDTreeShowBookmarks=1
" 在NERDTree显示git信息
let g:NERDTreeIndicatorMapCustom = {
			\ "Modified"  : "✹",
			\ "Staged"    : "✚",
			\ "Untracked" : "✭",
			\ "Renamed"   : "➜",
			\ "Unmerged"  : "═",
			\ "Deleted"   : "✖",
			\ "Dirty"     : "✗",
			\ "Clean"     : "✔︎",
			\ 'Ignored'   : '☒',
			\ "Unknown"   : "?"
			\ }
" <<<<<< NERDTree <<<<<<

" ------ 状态栏 ------
" >>>>>> airline >>>>>>
Plug 'vim-airline/vim-airline'
Plug 'vim-airline/vim-airline-themes'
let g:airline#extensions#tabline#enabled = 1
let g:airline#extensions#tabline#left_sep = ' '
let g:airline#extensions#tabline#left_alt_sep = '|'
let g:airline#extensions#tabline#formatter = 'unique_tail' " 'default'
" let g:airline_theme='luna'
let g:airline_theme='light'
let g:airline_theme='base16_solarized'
let g:airline_detect_modified=1
let g:airline_detect_paste=1
let g:airline_inactive_collapse=0
let g:airline_detect_spell=0
let g:airline_detect_crypt=1
"let g:airline_powerline_fonts=1
if !exists('g:airline_symbols')
	let g:airline_symbols = {}
endif
let g:airline_symbols.crypt = '?'
let g:airline_symbols.linenr = ''
let g:airline_symbols.maxlinenr = ''
let g:airline_symbols.branch = ''
let g:airline_symbols.paste = 'ρ'
let g:airline_symbols.notexists = '∄'
let g:airline_symbols.whitespace = 'Ξ'
let g:airline_left_sep = ''
let g:airline_left_alt_sep = '|'
let g:airline_right_sep = ''
let g:airline_right_alt_sep = '|'
" <<<<<< airline <<<<<<

" ------ 显示buffers ------
" >>>>>> bufferline >>>>>>
Plug 'bling/vim-bufferline'
" <<<<<< bufferline <<<<<<

" tag列表
" >>>>>> tagbar >>>>>>
Plug 'majutsushi/tagbar'
" tagbar开关快捷键
nmap <F8> :TagbarToggle<CR>
" <<<<<< tagbar <<<<<<

" 后台更新自动ctags
" >>>>>> vim-gutentags >>>>>>
Plug 'ludovicchabant/vim-gutentags'
Plug 'skywind3000/gutentags_plus'

" pip install pygments
" sudo apt install global
let $GTAGSLABEL = 'pygments'
let $GTAGSCONF = '/etc/gtags/gtags.conf'

" gutentags 搜索工程目录的标志，当前文件路径向上递归直到碰到这些文件/目录名
let g:gutentags_project_root = ['.git', '.root', '.svn', '.hg', '.project', 'MAINTAINERS', 'COPYING']

" 所生成的数据文件的名称
let g:gutentags_ctags_tagfile = '.tags'

" 同时开启 ctags 和 gtags 支持：
let g:gutentags_modules = []
if executable('ctags')
	let g:gutentags_modules += ['ctags']
endif
if executable('gtags-cscope') && executable('gtags')
	let g:gutentags_modules += ['gtags_cscope']
endif

" 将自动生成的 ctags/gtags 文件全部放入 ~/.cache/tags 目录中，避免污染工程目录
let g:gutentags_cache_dir = expand('~/.cache/tags')
" 检测 ~/.cache/tags 不存在就新建 "
if !isdirectory(g:gutentags_cache_dir)
   silent! call mkdir(g:gutentags_cache_dir, 'p')
endif

" 配置 ctags 的参数
let g:gutentags_ctags_extra_args = []
let g:gutentags_ctags_extra_args = ['--fields=+niazS', '--extras=+q']
let g:gutentags_ctags_extra_args += ['--c++-kinds=+px']
let g:gutentags_ctags_extra_args += ['--c-kinds=+px']

" 如果使用 universal ctags 需要增加下面一行
let g:gutentags_ctags_extra_args += ['--output-format=e-ctags']

" 禁用 gutentags 自动加载 gtags 数据库的行为
" 避免多个项目数据库相互干扰,使用plus插件解决问题
let g:gutentags_auto_add_gtags_cscope = 0

" change focus to quickfix window after search (optional).
let g:gutentags_plus_switch = 1

" default keymap
"<leader>cs	Find symbol (reference) under cursor
"<leader>cg	Find symbol definition under cursor
"<leader>cd	Functions called by this function
"<leader>cc	Functions calling this function
"<leader>ct	Find text string under cursor
"<leader>ce	Find egrep pattern under cursor
"<leader>cf	Find file name under cursor
"<leader>ci	Find files #including the file name under cursor
"<leader>ca	Find places where current symbol is assigned
" <<<<<< vim-gutentags <<<<<<

" ------ 语法检查 ------
" >>>>>> ale >>>>>>
Plug 'dense-analysis/ale'
" 设置检查工具
let g:ale_enabled = 0
let g:ale_linters_explicit = 1
let g:ale_linters = {
			\   'c': ['clang'],
			\   'c++': ['clang'],
			\   'bash': ['shellcheck'],
			\   'go': ['gofmt', 'golint'],
			\   'python': ['pylint'],
			\   'text': [],
			\}
" 检查时机配置
let g:ale_echo_delay = 20
let g:ale_lint_delay = 500
let g:ale_completion_delay = 500
let g:ale_lint_on_text_changed = 'normal'
let g:ale_lint_on_insert_leave = 1
let g:ale_lint_on_enter = 0
let g:ale_lint_on_save = 1
" 始终开启标志列
let g:ale_sign_column_always = 1
let g:ale_set_highlights = 1
" 自定义error和warning图标
let g:ale_sign_error = '✗'
let g:ale_sign_warning = '⚡'
" 设置状态栏显示的内容
set statusline=%F%m%r%h%w\ [FORMAT=%{&ff}]\ [TYPE=%Y]\ [POS=%l,%v][%p%%]\ %{strftime(\"%d/%m/%y\ -\ %H:%M\")}\ %{ALEGetStatusLine()}
" 在vim自带的状态栏中整合ale
let g:ale_statusline_format = ['✗ %d', '⚡ %d', '✔ OK']
" 显示Linter名称,出错或警告等相关信息
let g:ale_echo_msg_error_str = 'E'
let g:ale_echo_msg_warning_str = 'W'
let g:ale_echo_msg_format = '[%severity%][%linter%] %s'
" 普通模式下，错误或警告浏览快捷键
nmap <Leader>sp <Plug>(ale_previous_wrap)
nmap <Leader>sn <Plug>(ale_next_wrap)
" 触发/关闭语法检查快捷键
nmap <Leader>ss :ALEToggle<CR>
" 查看错误或警告的详细信息快捷键
nmap <Leader>sd :ALEDetail<CR>
" <<<<<< ale <<<<<<

" ------ 括号/引号成对插入/删除 ------
" >>>>>> auto-pairs >>>>>>
Plug 'jiangmiao/auto-pairs'
" let g:AutoPairs={'<':'>', '(':')', '[':']', '{':'}',"'":"'",'"':'"', "`":"`", '```':'```', '"""':'"""', "'''":"'''"}
" <<<<<< auto-pairs <<<<<<

" ------ 文件/buffer模糊查找 ------
" >>>>>> LeaderF >>>>>>
Plug 'Yggdroot/LeaderF', { 'do': './install.sh' }
" 运行:Leaderf -h命令查看帮助
" Ctrl + p 打开文件搜索
let g:Lf_ShortcutF = '<C-p>'
noremap <Leader>ff :LeaderfFunction<cr>
noremap <Leader>fb :LeaderfBuffer<cr>
noremap <Leader>ft :LeaderfTag<cr>
noremap <Leader>fm :LeaderfMru<cr>
noremap <Leader>fl :LeaderfLine<cr>

let g:Lf_StlSeparator = { 'left': '', 'right': '', 'font': '' }
let g:Lf_RootMarkers = ['.project', '.root', '.svn', '.git']
let g:Lf_WorkingDirectoryMode = 'Ac'
let g:Lf_WindowHeight = 0.30
let g:Lf_CacheDirectory = expand('~/.vim/cache')
let g:Lf_ShowRelativePath = 0
let g:Lf_HideHelp = 1
let g:Lf_StlColorscheme = 'powerline'
let g:Lf_PreviewResult = {'Function':0, 'BufTag':0}

let g:Lf_NormalMap = {
			\ "File":   [["<ESC>", ':exec g:Lf_py "fileExplManager.quit()"<CR>']],
			\ "Buffer": [["<ESC>", ':exec g:Lf_py "bufExplManager.quit()"<CR>']],
			\ "Mru":    [["<ESC>", ':exec g:Lf_py "mruExplManager.quit()"<CR>']],
			\ "Tag":    [["<ESC>", ':exec g:Lf_py "tagExplManager.quit()"<CR>']],
			\ "Function":    [["<ESC>", ':exec g:Lf_py "functionExplManager.quit()"<CR>']],
			\ "Colorscheme":    [["<ESC>", ':exec g:Lf_py "colorschemeExplManager.quit()"<CR>']],
			\ }
" <<<<<< LeaderF <<<<<<

" 搜索工具
" vim自带命令vimgrep
" >>>>>> ack >>>>>>
Plug 'mileszs/ack.vim'
" 用法:Ack [options] {pattern} [{directories}]
if executable('ag')
	let g:ackprg = 'ag --vimgrep'
endif
" <<<<<< ack <<<<<<

" ------ 文件模板 ------
" >>>>>> template >>>>>>
Plug 'tibabit/vim-templates'
" <<<<<< template <<<<<<

" 高亮关键字
" >>>>>> Mark--Karkat >>>>>>
Plug 'vim-scripts/Mark--Karkat'
" 部分内置快捷键
" <Leader>m 高亮/取消选中的单词
" <Leader>n 取消高亮的所有单词
" <Leader>/ 查找高亮的所有单词
" VIM内置的类似的高亮搜索功能:
" shift + * 向后搜索光标所在位置的单词
" shift + # 向前搜索光标所在位置的单词
" <<<<<< Mark--Karkat <<<<<<

" 行尾空格显示告警色
" >>>>>> better-whitespace >>>>>>
Plug 'ntpeters/vim-better-whitespace'
let g:better_whitespace_enabled=1
let g:strip_whitespace_on_save=1
let g:strip_whitelines_at_eof=1
let g:show_spaces_that_precede_tabs=1
" <<<<<< better-whitespace <<<<<<

" Initialize plugin system
call plug#end()
" <<<<<<<< 插件管理 <<<<<<<<
